import 'dart:io';
import 'dart:typed_data';

import 'package:dio/dio.dart';
import 'package:shortmovieapp/common.dart';
import 'package:shortmovieapp/http/core/HttpRequest.dart';
import 'package:shortmovieapp/http/core/http_adapter.dart';
import 'package:shortmovieapp/http/core/http_error.dart';

import 'http_response.dart';



class DioAdapter extends HttpAdapter {

  static DioAdapter? _instance;
  DioAdapter._(){
    Debug.log("DioAdapter init");
  }
  factory DioAdapter (){
    _instance??= DioAdapter._();
    return _instance!;
  }

  @override
  Future<HttpResponse> send(HttpRequest request) async {
    Debug.log("DioAdapter send:${request.url}");
    Response<dynamic>? response;
    var options = Options(headers: request.headers,contentType: request.contentType);
    DioException? error;
    try {
      if (request.httpMethod == HttpMethod.Get) {
        String url = request.getUrlWithParams();
        //Debug.log("get url:$url");
        response = await Dio().get(url, options: options);
      } else if (request.httpMethod == HttpMethod.Post) {
        response = await Dio()
            .post(request.url, data: request.params, options: options);
      } else if (request.httpMethod == HttpMethod.Delete) {
        response = await Dio()
            .delete(request.url, data: request.params, options: options);
      }
    } on DioException catch (e) {
      error = e;
      response = e.response;
    }

    if (error != null || response == null) {
          Debug.log("dio send error:${error.toString()}\n ${response?.toString()}");
         return HttpResponse(code: -1, 
         message: error!.error.toString(),
         request: request,
         data: response?.data.toString());
    }

    //Debug.log("DioAdapter send end data:${response.data}  code:${response.statusCode}");
    return buildResult(response, request);
  }

  HttpResponse buildResult(Response response, HttpRequest request) {
    return HttpResponse(
        code: response.statusCode ?? -1,
        message: response.statusMessage ?? "",
        request: request,
        data: response.data,
        extra: response);
  }

  @override
  Future<HttpResponse> sendFile(HttpRequest request, String file)async {
    Debug.log("DioAdapter send:${request.url}");
    Response<dynamic>? response;
    DioException? error;

     var options = Options(
      // headers: { Headers.contentLengthHeader: bytes.length,}
      //contentType: "multipart/form-data"
     );

    var formData = FormData();
    formData.files.add(MapEntry('file', await MultipartFile.fromFile(file)));
    request.params.forEach((key, value) {
        formData.fields.add(MapEntry(key, value));
        Debug.log("add field key:${key}  value:${value}");
    });

    try {
      var url = request.url + request.getParamString();
      Debug.log("send with data url:${request.url}  options:${options.contentType}");
      response = await Dio().post( request.url,data: formData, options: options,);
    } on DioException catch (e) {
      error = e;
      response = e.response;
    }
    if (error != null || response == null) {
          Debug.log("dio send error:${error.toString()}\n ${response?.toString()}");
         return HttpResponse(code: -1, 
         message: error!.error.toString(),
         request: request,
         data: response?.data.toString());
    }

    Debug.log("DioAdapter send end data:${response.data}  code:${response.statusCode}");
    return buildResult(response, request);
  }
}
